///*--------------------------------------------------------------------------
//    This source file is part of Abraxas Game Engine
//    For the latest info, see http://code.google.com/abraxasge/
//    Copyright (C) 2009, Andrew LeRoy <aleroy@member.igda.org>
//    ---
//
//    This program is free software; you can redistribute it and/or
//    modify it under the terms of the GNU General Public License
//    as published by the Free Software Foundation; either version 2
//    of the License, or (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin Street, Fifth Floor,
//    Boston, MA  02110-1301, USA.
//--------------------------------------------------------------------------*/
//#include "AbxSystem.hpp"
//#include "AbxLogManager.hpp"
//#include "AbxString.hpp"
//#include "AbxException.hpp"
//#include <typeinfo>
//
//namespace Abx
//{
//    //-----------------------------------------------------------------------
//    // OneInstance::OneInstance (default c'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    OneInstance<T>::OneInstance()
//    {
//        instance_ = NULL;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneInstance::~OneInstance (default d'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    OneInstance<T>::~OneInstance<T>()
//    {
//        //delete instance_;
//        instance_ = 0;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneInstance::insert
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void OneInstance<T>::insert(T* instance)
//    {
//        instance_ = instance;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneInstance::erase
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> OneInstance<T>::erase(T* instance)
//    {
//        Optional<T*> optinst;
//        if (instance_ && instance_->getName() == instance->getName())
//        {
//            optinst = instance_;
//            instance_ = 0;
//        }
//        return optinst;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneInstance::get
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> OneInstance<T>::get(String const& name, bool byTypeName) const
//    {
//        Optional<T*> optinst;
//        if (instance_)
//        {
//            if (byTypeName)
//            {
//                if (instance_->getTypeName == name)
//                { optinst = instance_; }
//            }
//            else
//            {
//                if (instance_->getName() == name)
//                { optinst = instance_; }
//            }
//        }
//        return optinst;
//    }
//
//
//
//
//
//    //-----------------------------------------------------------------------
//    // ManyInstances::ManyInstances (default c'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    ManyInstances<T>::ManyInstances()
//    { }
//
//    //-----------------------------------------------------------------------
//    // ManyInstances::~ManyInstances (default d'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    ManyInstances<T>::~ManyInstances<T>()
//    {
//        instances_.clear();
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyInstances::insert
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void ManyInstances<T>::insert(T* instance)
//    {
//        instances_[instance->getName()] = instance;
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyInstances::erase
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> ManyInstances<T>::erase(T* instance)
//    {
//        Optional<T*> optinst;
//        instance_it it = instances_.find(instance->getName());
//        if (it != instances_.end())
//        {
//            optinst = it->second;
//            instances_.erase(it);
//        }
//        return optinst;
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyInstances::get
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> ManyInstances<T>::get(String const& name, bool byTypeName) const
//    {
//        Optional<T*> optinst;
//
//        instance_cit cit;
//        if (byTypeName)
//        {
//            for (cit = instances_.begin(); cit != instances_.end(); ++cit)
//            {
//                if (cit->second->getTypeName() == name)
//                { optinst = cit->second; }
//            }
//        }
//        else
//        {
//            cit = instances_.find(name);
//            if (cit != instances_.end())
//            { optinst = cit->second; }
//        }
//        return optinst;
//    }
//
//
//
//
//
//
//    //-----------------------------------------------------------------------
//    // OneFactory::OneFactory (default c'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    OneFactory<T>::OneFactory() : factory_(NULL), counter_(0)
//    { }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::~OneFactory (default d'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    OneFactory<T>::~OneFactory<T>()
//    {
//        delete options_;
//        delete factory_;
//        factory_ = 0;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::add
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void OneFactory<T>::add(factory_type* factory)
//    {
//        factory_ = factory;
//        options_ = &factory->getOptions();
//    }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::remove
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void OneFactory<T>::remove(factory_type* factory)
//    {
//        delete options_;
//        delete factory_;
//        factory_ = 0;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::get
//    //-----------------------------------------------------------------------
//
//    export template <class T>
//    Optional<typename T::factory_type*> OneFactory<T>::get(const String& typeName) const
//    {
//        Optional<factory_type*> optfact;
//        if (factory_ && factory_->getOptions().typeName == typeName)
//        {
//            optfact = factory_;
//        }
//        return optfact;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::getOptions
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<const typename T::options_type*> OneFactory<T>::getOptions(const String& typeName) const
//    {
//        Optional<const typename T::options_type*> optoptions;
//        if (typeName == options_->typeName)
//        {
//            optoptions = options_;
//        }
//        return optoptions;
//    }
//
//    //-----------------------------------------------------------------------
//    // OneFactory::create
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> OneFactory<T>::create(String const& typeName, String const& instanceName)
//    {
//        Optional<T*> optinst;
//        if (factory_ && factory_->getOptions().typeName == typeName)
//        {
//            if (instanceName.empty())
//            {
//                StringTools::StrStreamType s;
//                s << typeName << "_" << ++counter_;
//                optinst = factory_->createInstance(s.str());
//            }
//            else
//            {
//                optinst = factory_->createInstance(instanceName);
//            }
//        }
//        return optinst;
//    }
//
//
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::ManyFactories (default c'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    ManyFactories<T>::ManyFactories()
//        : counter_(0)
//    { }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::~ManyFactories (default d'stor)
//    //-----------------------------------------------------------------------
//    export template <class T>
//    ManyFactories<T>::~ManyFactories<T>()
//    {
//        factories_.clear();
//        options_.clear();
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::add
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void ManyFactories<T>::add(factory_type* factory)
//    {
//        factories_.push_back(factory);
//        options_.push_back(&factory->getOptions());
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::remove
//    //-----------------------------------------------------------------------
//    export template <class T>
//    void ManyFactories<T>::remove(factory_type* factory)
//    {
//        // remove associated options
//        for (options_list_iter it = options_.begin(); it != options_.end(); ++it)
//        {
//            if (*it == &(factory->getOptions()))
//            {
//                options_.erase(it);
//                //break;
//            }
//        }
//        factories_.remove(factory);
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::get
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<typename T::factory_type*> ManyFactories<T>::get(const String& typeName) const
//    {
//        Optional<factory_type*> optfact;
//        for (factory_list_iter it = factories_.begin(); it != factories_.end(); ++it)
//        {
//            if ((*it)->getOptions().typeName == typeName)
//            {
//                optfact = *it;
//                break;
//            }
//        }
//        return optfact;
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::getOptions
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<const typename T::options_type*> ManyFactories<T>::getOptions(const String& typeName) const
//    {
//        Optional<const typename T::options_type*> optoptions;
//        for (options_list_citer cit = options_.begin(); cit != options_.end(); ++cit)
//        {
//            if (typeName == (*cit)->typeName)
//            {
//                optoptions = *cit;
//            }
//        }
//        return optoptions;
//    }
//
//    //-----------------------------------------------------------------------
//    // ManyFactories::create
//    //-----------------------------------------------------------------------
//    export template <class T>
//    Optional<T*> ManyFactories<T>::create(String const& typeName, String const& instanceName)
//    {
//        Optional<T*> optinst;
//        for (factory_list_iter it = factories_.begin(); it != factories_.end(); ++it)
//        {
//            if ((*it)->getOptions().typeName == typeName)
//            {
//                if (instanceName.empty())
//                {
//                    StringTools::StrStreamType s;
//                    s << typeName << "_" << ++counter_;
//                    optinst = (*it)->createInstance(s.str());
//                }
//                else
//                {
//                    optinst = (*it)->createInstance(instanceName);
//                }
//                break;
//            }
//        }
//        return optinst;
//    }
//
//
//
//
//    //-----------------------------------------------------------------------
//    // System::System (default c'stor)
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::System()
//    { }
//
//    //-----------------------------------------------------------------------
//    // System::System (default d'stor)
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::~System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>()
//    { }
//
//
//    //-----------------------------------------------------------------------
//    // System::Register
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    void System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Register(factory_type* factory)
//    {
//        factoryPolicy_.add(factory);
//        LogManager::Instance().logMessage("Registered a system factory for '"
//            + factory->getOptions().typeName + "'");
//    }
//
//    //-----------------------------------------------------------------------
//    // System::Unregister
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    void System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Unregister(factory_type* factory)
//    {
//        // make sure this is a registered factory
//        String typeName = factory->getOptions().typeName;
//        Optional<factory_type*> optfact = factoryPolicy_.get(typeName);
//        if (optfact.invalid())
//        {
//            String systemName;
//            systemName = typeid(*this).name;
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "Could not unregister '" + typeName + "'; the system is not currently registered",
//                systemName +"::Unregister");
//        }
//
//        // destroy all instances created by this factory
//        for (Optional<T*> optinst = instancePolicy_.get(typeName, true);
//                optinst.valid();
//                optinst = instancePolicy_.get(typeName, true))
//        {
//            optinst = instancePolicy_.erase(*optinst);
//        }
//        factoryPolicy_.remove(factory);
//        LogManager::Instance().logMessage("Unregistered a system factory for '"
//            + factory->getOptions().typeName + "'");
//    }
//
//    //-----------------------------------------------------------------------
//    // System::getOptions
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    const typename T::options_type* System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::getOptions(String const& typeName) const
//    {
//        Optional<typename T::options_type const*> optoptions = factoryPolicy_.getOptions(typeName);
//        if (optoptions.invalid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "System options were not found or do not exist for a system of type '" + typeName + "'",
//                systemName +"::getOptions");
//        }
//        return *optoptions;
//    }
//
//    //-----------------------------------------------------------------------
//    // System::Create
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    T* System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Create(String const& typeName, String const& instanceName)
//    {
//        Optional<T*> optinst = instancePolicy_.get(instanceName);
//        if (optinst.valid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
//                "System of type '" + typeName + "' already has an instance called '" + instanceName + "'",
//                systemName + "::Create");
//        }
//        optinst.clear();
//
//        optinst = factoryPolicy_.create(typeName, instanceName);
//        if (optinst.invalid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "No factory found for a system of type '" + typeName + "'",
//                systemName + "::Create");
//        }
//        return *optinst;
//    }
//
//    //-----------------------------------------------------------------------
//    // System::Destroy
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    void System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Destroy(T* instance)
//    {
//        Optional<T*> optinst = instancePolicy_.erase(instance);
//        if (optinst.invalid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "Unable to destroy instance '" + instance->getName() + "' because an instance with that name was not found",
//                systemName + "::Destroy");
//        }
//
//        Optional<factory_type*> optfact = factoryPolicy_.get(instance->getTypeName());
//        if (optfact.invalid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "Unable to destroy instance '" + instance->getName() + "' because a valid factory was not found",
//                systemName + "::Destroy");
//        }
//        (*optfact)->destroyInstance(instance);
//    }
//
//    //-----------------------------------------------------------------------
//    // System::getInstance
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    T* System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::getInstance(String const& instanceName) const
//    {
//        Optional<T*> optinst = instancePolicy_.get(instanceName);
//        if (optinst.invalid())
//        {
//            String systemName(typeid(*this).name);
//            ABX_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
//                "Instance with name '" + instanceName + "' not found",
//                systemName + "::getInstance");
//        }
//        return *optinst;
//    }
//
//    //-----------------------------------------------------------------------
//    // System::Update
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    bool System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Update()
//    {
//        return true;
//    }
//
//    //-----------------------------------------------------------------------
//    // System::Update(T* instance)
//    //-----------------------------------------------------------------------
//    export template
//    <
//        class T,
//        template <class> class FactoryPolicy,
//        template <class> class InstancePolicy,
//        template <class, class> class EventModel,
//        typename EventAllocator
//    >
//    bool System<T, FactoryPolicy, InstancePolicy, EventModel, EventAllocator>
//        ::Update(T* instance)
//    {
//        return true;
//    }
//
//} // namespace Abx
